package dryven.request.controller.result;

import dryven.model.binding.proxy.Binding;
import dryven.request.RedirectStatus;
import dryven.request.controller.ControllerDescription;
import dryven.request.http.Request;
import dryven.request.http.Response;
import dryven.request.routing.RoutingService;

/**
 * Does a true HTTP redirect.
 * The difference with ForwardResult is that this is not an internal redirect but 
 * sends the browser a redirect reply so it can request the new resource.
 * One of the advantages is that the user is notified of the new location through the
 * browser url bar.
 * The disadvantage is that all parameters to a controller action have to be
 * serializable by the router and deserializable by the action parameter transformers.
 * This is usually only true for primitive types, strings, enums and persisted entity models
 * @author bwindels
 *
 */
public class RedirectResult implements ActionResult {
	
	private RedirectStatus _status;
	private ControllerDescription _cd;
	private String _url;
	
	public RedirectResult(Binding<ActionResult> action, RedirectStatus status) {
		this(new ControllerDescription(action),status);
	}
	
	public RedirectResult(ControllerDescription action, RedirectStatus status) {
		_cd = action;
		_status = status;
	}
	
	public RedirectResult(String url, RedirectStatus status) {
		_url = url;
		_status = status;
	}
	
	public RedirectResult(Binding<ActionResult> action) {
		this(action,RedirectStatus.Temporarily);
	}
	
	public RedirectResult(ControllerDescription action) {
		this(action,RedirectStatus.Temporarily);
	}
	
	public RedirectResult(String url) {
		this(url,RedirectStatus.Temporarily);
	}
	
	public void injectDependencies(RoutingService routing) {
		if(_cd!=null) {
			_url = routing.controllerToRoute(_cd);
		}
	}
	
	@Override
	public ActionResult process(Request req, Response resp) {
		resp.setStatus(_status.getCode());
		resp.setHeader("Location",_url);
		return null;
	}

}
